/*
  zuino.cpp - Library for zulio utility.
  Created by Guido Zuliani (zulio), January 15, 2012.
  Released into the public domain.
*/
#include "zuino.h"

// -------------- ZELEMENT START ------------

ZElement::ZElement(int pin)
{
    _PIN = pin;
    _reset();
}

unsigned long ZElement::current_millis()
{
    unsigned long current_time_millis;
    cli();  // disable interrupts
    current_time_millis = millis();
    sei();  // enable interrupts 
    return current_time_millis;  
}

// --------------- ZELEMENT END -------------

// -------------- ZBUTTON START -------------

ZButton::ZButton(int pin) : ZElement(pin)
{
    pinMode(pin, INPUT);
    _reset();
}

void ZButton::_reset()
{
    ZElement::_reset();
    _enable = true;
    _enable_long_pression = false;
    _long_time_pression_millis = 1000UL;
    _prev_state = LOW;
    _first_pression_millis = 0;

    _pressed = false;
    _pressing = false;
    _long_pressing = false;  
}

unsigned long ZButton::refresh(unsigned long current_mills)
{  
  if(!_enable)
  {
    _reset();
    return current_mills;
  }

 
  unsigned long current_time_millis = current_mills;
  if(_enable_long_pression)
  {
      if(current_time_millis==0)
        current_time_millis = current_millis();    
  }  
  
  unsigned int current_state = digitalRead(_PIN);
  if((current_state==HIGH) && (_prev_state==LOW))
  {
    _pressed = true;
    _first_pression_millis = current_time_millis;
  }
  else
    _pressed = false;
  
  if(_enable_long_pression)
  {
      if((current_state==HIGH) && (_prev_state==HIGH))
      {
        if(current_time_millis-_first_pression_millis>_long_time_pression_millis)
          _long_pressing = true;
        else
          _long_pressing = false;
      }
  }
  else
     _long_pressing = false;
   
  if(current_state==LOW)
  {
    _long_pressing = false;
    _pressing = false;
  }
  else
    _pressing = true;

  _prev_state = current_state;
  
  return current_time_millis;
}
// -------------- ZBUTTON END --------------

// --------------- ZLED START --------------
ZLed::ZLed(int pin) : ZElement(pin)
{
  pinMode(pin, OUTPUT); 
  _reset();
}

void ZLed::_reset()
{  
    ZElement::_reset();
    _state = LOW;
    _blinking = false;
    _bink_until_millis = 0;
    _enable_blinking = false;
}

unsigned long ZLed::blink_for(int milliseconds, unsigned long current_mills)
{
  if(_enable_blinking)
  {
    _blinking = true;  
    _bink_until_millis = current_mills + milliseconds;
    turn_on();
  }
}

unsigned long ZLed::blink_for(int milliseconds)
{
  return blink_for(milliseconds, current_millis());
}

void ZLed::invert_state()
{
  if(_state==LOW)
    turn_on();
  else
    turn_off();
}  

void ZLed::turn_on()
{
  _state = HIGH;
  digitalWrite(_PIN, _state);
}

void ZLed::turn_off()
{
  _state = LOW;
  digitalWrite(_PIN, _state);
}

 
unsigned long ZLed::refresh(unsigned long current_mills)
{
    unsigned long current_time_millis = current_mills;
    if(_enable_blinking)
    {
      if(current_time_millis==0)
        current_time_millis = current_millis();

      if(_blinking && current_time_millis>_bink_until_millis)
      {
        turn_off();
        _blinking = false;
      }
    }
    return current_time_millis;
}

// ---------------- ZLED END ---------------

// ------------ ZMANAGER START --------------
ZManager::ZManager()
{
  _next_element = 0;
}

boolean ZManager::add(ZElement *element)
{
  if(_next_element<MAX_ZELEMENTS_IN_MANAGER)
  {
    _elements[_next_element] = element;
    _next_element++;
    return true;
  }
  else
    return false;
}

unsigned long ZManager::refresh(unsigned long current_millis)
{
  unsigned long millis_for_current = current_millis;
  ZElement *current_element;
  for(int i=0;i<_next_element;i++)
  {
    current_element = _elements[i];
    millis_for_current = current_element->refresh(millis_for_current);
  }  
  return millis_for_current;
}

// -------------- ZMANAGER END --------------
